/*! 
 * Implementation file for the particle class.
 *
 * \author Devis Rossini
 * \date 25 May 2012
 */ 
#include "PhxParticle.h"

#include <cassert>

using namespace phx;

void Particle::Integrate(real duration)
{
	// We don't integrate things with zero mass.
	if (mInverseMass <= 0.0f) return;

	assert(duration > 0.0);

	// Update linear position.
	mPosition.AddScaledVector(mVelocity, duration);

	// Work out the acceleration from the force.
	Vector3 resultingAcc = mAcceleration;
	resultingAcc.AddScaledVector(mForceAccumulator, mInverseMass);

	// Update linear velocity from the acceleration.
	mVelocity.AddScaledVector(resultingAcc, duration);

	// Impose drag.
	mVelocity *= real_pow(mDamping, duration);

	// Clear the forces.
	ClearAccumulator();
}

void Particle::SetMass(const real mass)
{
	assert(mass != 0);
	mInverseMass = ((real)1.0) / mass;
}

real Particle::GetMass() const
{
	if (mInverseMass == 0) 
	{
		return REAL_MAX;
	} 
	else 
	{
		return ((real)1.0) / mInverseMass;
	}
}

void Particle::SetInverseMass(const real inverseMass)
{
	mInverseMass = inverseMass;
}

real Particle::GetInverseMass() const
{
	return mInverseMass;
}

bool Particle::HasFiniteMass() const
{
	return mInverseMass >= 0.0f;
}

void Particle::SetDamping(const real damping)
{
	mDamping = damping;
}

real Particle::GetDamping() const
{
	return mDamping;
}

void Particle::SetPosition(const Vector3& position)
{
	mPosition = position;
}

void Particle::SetPosition(const real x, const real y, const real z)
{
	mPosition.x = x;
	mPosition.y = y;
	mPosition.z = z;
}

void Particle::GetPosition(Vector3* position) const
{
	*position = mPosition;
}

Vector3 Particle::GetPosition() const
{
	return mPosition;
}

void Particle::SetVelocity(const Vector3& velocity)
{
	mVelocity = velocity;
}

void Particle::SetVelocity(const real x, const real y, const real z)
{
	mVelocity.x = x;
	mVelocity.y = y;
	mVelocity.z = z;
}

void Particle::GetVelocity(Vector3* velocity) const
{
	*velocity = mVelocity;
}

Vector3 Particle::GetVelocity() const
{
	return mVelocity;
}

void Particle::SetAcceleration(const Vector3& acceleration)
{
	mAcceleration = acceleration;
}

void Particle::SetAcceleration(const real x, const real y, const real z)
{
	mAcceleration.x = x;
	mAcceleration.y = y;
	mAcceleration.z = z;
}

void Particle::GetAcceleration(Vector3* acceleration) const
{ 
	*acceleration = mAcceleration;
}

Vector3 Particle::GetAcceleration() const
{
	return mAcceleration;
}

void Particle::ClearAccumulator()
{
	mForceAccumulator.Clear();
}

void Particle::AddForce(const Vector3& force)
{
	mForceAccumulator += force;
}
